﻿using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;

namespace BrnMall.Sdk.WeiXin.Tool
{
    public class JsonHttps
    {
        public static T Get<T>(string url, Merchant math)
        {
            var result = Get(url, math);
            return JsonConvert.DeserializeObject<T>(result);
        }
        public static string Get(string url, Merchant math)
        {
            Trace.TraceInformation(url);
            var request = CreateRequest(url, "GET");
            SetAuthHeader(math, request);
            try
            {
                return GetData(request);
            }
            catch (WebException ex)
            {
                var res = (HttpWebResponse)ex.Response;
                var myResponseStream = res.GetResponseStream();
                var sr = new StreamReader(myResponseStream, Encoding.UTF8);
                string resString = sr.ReadToEnd();
                sr.Close();
                throw new WebException(resString);
            }
        }

        public static string Post(string url, string data, Merchant math)
        {
            Trace.TraceInformation(url);
            Trace.TraceInformation(data);
            var request = CreateRequest(url, "POST");
            SetAuthHeader(math, request, data);
            var postData = Encoding.UTF8.GetBytes(data);
            request.ContentLength = postData.Length;
            using (var stream = request.GetRequestStream())
            {
                stream.Write(postData, 0, postData.Length);
            }
            try
            {
                var result = GetData(request);
                return result;
            }
            catch (WebException ex)
            {
                var res = (HttpWebResponse)ex.Response;
                var myResponseStream = res.GetResponseStream();
                var sr = new StreamReader(myResponseStream, Encoding.UTF8);
                string resString = sr.ReadToEnd();
                sr.Close();

                LogUtil.WriteLog("coupon", $"{url}\r\n{data}\r\n{resString}");
                throw new WebException(resString);
            }
            return string.Empty;
        }

        public static T Post<T>(string url, string data, Merchant math)
        {
            var result = Post(url, data, math);
            return JsonConvert.DeserializeObject<T>(result);
        }

        public static string GetData(HttpWebRequest request)
        {
            var result = string.Empty;
            var response = (HttpWebResponse)request.GetResponse();
            var resStream = response.GetResponseStream();
            if (resStream != null)
                result = new StreamReader(resStream).ReadToEnd();
            Trace.TraceInformation(result);
            return result;
        }

        protected static HttpWebRequest CreateRequest(string url, string method)
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = method;
            return request;
        }

        public static void SetAuthHeader(Merchant math, HttpWebRequest request, string postData = "")
        {
            var auth = BuildAuth(request, postData, math);
            request.Headers.Add("Authorization", $"WECHATPAY2-SHA256-RSA2048 {auth}");

            request.ContentType = "application/json";
            request.Accept = "application/json";
            request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36";
        }

        public static string BuildAuth(HttpWebRequest request, string postData, Merchant math)
        {
            string method = request.Method.ToUpper();
            string body = "";
            if (method == "POST" || method == "PUT" || method == "PATCH")
            {
                body = postData;
            }
            string uri = request.RequestUri.PathAndQuery;
            var timestamp = GetTimeStamp();
            string nonce = Path.GetRandomFileName();

            string message = $"{method}\n{uri}\n{timestamp}\n{nonce}\n{body}\n";
            string signature = Sign(message, math);
            return $"mchid=\"{math.MachId}\",nonce_str=\"{nonce}\",timestamp=\"{timestamp}\",serial_no=\"{math.Cert_No}\",signature=\"{signature}\"";
        }

        //public static string Sign_old(string message, Merchant math)
        //{
        //    // NOTE： 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY-----
        //    //        亦不包括结尾的-----END PRIVATE KEY-----
        //    //企动
        //    //string privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDnwk/nt2ibAizDREHOqmjWkX5ao1vWrmx/zirVT2EOIy3rXvZ8TmHESV7yHPnkWNKfELD734/9yKPtNjDZGg7o8WpF1mmG/sBJAKpKvnBU7zxnjkg/0PQCa41LR0eJAuKVpWA2ry7Z8g19iAK8MTYHW4bQYxZQafRkY0y2AtDpf7hGgwuqQ15qt6fGJKDnHLjL2HyjAIWrsFd1CludGBQEhunaf+9AeoSTguuMrmkAnatnQzfB18F/aMNLBioeT7h8o+pUby0t/LmYE/b7MurLB/2ERw9RxHDXCr9isypEjuMj4hmqghQg1wZQa1S2m5HmymcGb6G052v0YInIVWmlAgMBAAECggEAJA5jCBXMvHD2Ldrssg5pCRjRo6BOpXO1hZy5pT4YR27JshiwGF7JbxRLJTfE2PXIrt6V6lm5uS4B8uG/b8dSEoOcmQjmmg4ANFtaIw7FwzEFIMdODj+f9tBsxw1r37EHN2jnMxrGGzpBRwpmAolVcoeWzczcp94UG5onURnXDrx4SckN9JBO9o763RdifR3eyKhUcxmf2aWIWDv8dwcyqTJGQIIbfHfbPv3ZqzxoWWH8GcOhqXvXBhng3kZ3RT+1OpaWB/CRfkJV6aowqcLHuXfXz4Aj3ZDy0HK6JKws0YfxBmZkGf1RhzoSgMTQZtc9Cj2rJmxZqU0G99ArsMBn8QKBgQD5/8i9TVyYfhfh00updWI4JTJG8CTTKHKDq/nBqjq656Q5oOHYu6GDR1vSEyVtZslRPrizLAy9LfXgIFOqDXIXa4jHLPH62F2m8t8VFQipYXC4JwGPqn0MXhtCTbyM6mVCXtXqGGHn2K2sEgKIGRx2mv6S0fmsEjhtlkOpmADviwKBgQDtUnHNER6GR3dDfHuTZt92vsZrpQwH/4qByfXed755I/4euvbenUTgLxm5vHiFv+9UvcoBSwjE/1+hYVlHOpIK3TAC8+cD9usyFJUjR//WC39WDW39DLG9a3BgrMHzesilu4VxvuHq4yMuyTkQnbTXKpX2cySB5ZqZaa8d1KIxjwKBgH5MZ8ijDbWIdl5DFgVtZQqCWC0YYzI+S+QTfOEHNBZ6si/fBFovKICfC1dNDup/NBOUgVEbXvAwCPiKvFm74zjLvdUJ8tHMfzu5lVQcRTz1GjIemp5O/k/CNzk+9pOmUzO9n4pdeRDdGZhFnPvO299bnGLmK6FvrwxGDrbeMRLTAoGAblzxuSil5lIjv0mLej/T2bfcNED7uFh5A+R0p3FOLa20Rnwxw9KlLhAZSYvBDIn2dZUQ9Mr9GAeeZEEOMJanRdAYvLbKDsjsFU0HEfIwokyUeeMi7BPUMD9fckXEqELIPnJXG09mZkIcoWxIUlbUu179gC+JobKx03gXTKsOhjcCgYEAxzdo7UjdsPZchRiLC3D6X2WxwZAh4/8XmWH00U8dEb5YhphGUVf/M7XaK2SAUxxpVyIA5ImXm4fdr/DgOBip1/TPG9kuiUSC6gsth7eTWs++LQWQwRe3Af3h2LPZJXb21SET5hBNB8gMWePHd/Y03m22PGHGIiWj9HP/+g4KRBY=";

        //    //小资馆
        //    //var privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzJQkvlEb30A5X4W+avUEHyAgEgcFF/oLijNhNGIHK2iTmtWfIONOYcSB7vMYdBf0hTHmtA8PeD20XwX3KA8+5IQm3KgQzdR1bf8oM+Pi5pbmVdLyKJ3bna9/PJvxsTMD0RCm+R6IbzjYXykw8bw257WMgm7NM4u5AdPKVpP/Y5A1qlRzJPZ8QTrfxX1o2HWgcn1zqDSlSytDgS8sS/8zlS77c/499dSuRMjohqJ8MT7bLsN3oSk6u9OFu/4FE/lgAk9XDOdXMW3YPr/tevkrxxutpepwuIhpme/AU6co+bQ3981Ot17Nh5HvgLqLCU/K25IfuOl/cJedRmgJXTAb7AgMBAAECggEAVbYWmwkam16UPj/CIgsCnjJ6g42BZ3fKL5KrutdK4j9VAH0y1n053+ngXNOJBkHjRpdMcBcpE4nV7FPLV2hTboP8HgKgV+5kyW5uwZ4tgsVj8boUqxUOstLOFlLU2wwuFbC3OC8VxK/4+ZD0wMVxj8+gae2U7+hzjatmlWqIbsCAyMpBflbFfBUeGJ4sek9w7GxW9lvIo1lYromblXCPEyD7Wb1OjEw3s4bhTBYJiyfXIyVlWjQF5h7AZv253ylSkjizQo+hMUty6xTuHx359IO8SlsZBPfoEg2tF0y3jOpsU3L6WXB4Il+6Mlk2JXo4Yf9sxykiFsOV5I51GiicoQKBgQDj5HpUUVA17UUg1tu4dRVswhM16ZnlQZ2JY12JzsBgLVlLTvoULpLOslx8Hv6jc/rEKKoeKKEg3ZRn8OhSHD3FHlKll3CIfbqmIa1yPGiiGlWZ/HzWUfYcntns6XJ5e2/jg+9pT2oVg6N2fcxiFilbZ45txInQG7ToOJuw8dsO9QKBgQDJPWKDKjvSdz08dzF1EzKKXF2vpnUJniRUtxMTMe0Gu4n17s/jiXLe+prrekr4OLuaeHg6k2YqXxI9a/LMCYnb2AGXqvZvsAoY7j1fyijHnfO+lO+jLXK36PYtUoJlSix54jrtoZTChN9OUtgCsybrEuwKoSq41dnSIKHibAYoLwKBgQCXLRLlakeObobEISQCulDrI9eAlSWNCrkJ0cvURj4hzxOEPLDywG6NBY8Km7kKDz8T73HircsttS/kv9At4CQt5k6nIM37DYTK/l5EAMTcfCG7E95wglCEbfBdFAPniLYRtI0WTCMwgHHogc0aaF8pDopSUOWnEyowPpUxjU9nHQKBgBBCTGZKkEDF74WmH7HU1j2FjvA1I7meNFM/42Omof7sQg5DuDorDcPkPYYPAGWjt8yYNSaOaC++NKwPv7Mqhh/kCOTnJDgL4hT3kq/dloPiSCI6yE3Hyz/+q30n8G8cmhFS7O3sIyfAMoaSfO9i6B8QDVAii2AZrxqiFlJD5g9zAoGAAInQjRryLS3Mc6uH0WI8i6IZFzBMLw6pRU+p9aWwxtbdZwZa+KaMWbFpFyyNb68EyzEoqBKc5yvfnNi6CguxljmFAk92bJY5q71+1uRHh1UiC5XH+C1PJtllIkJyXv6vFSUQcJJnmUa4BybwBu8US7bcslLcnm8sC+YE4rJMTnA=";

        //    //服务商
        //    //var privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDACE5xfu2fJk1H9I990y1Oz7dl49Feo9v6grreqN3sxFCMWc+AEbNoU7bLwxaBf4HObMNPVgpdQZWH1b/JA86NDHSdNdkspkVGOm49drfJ7CaXzeYjJEs1/nxOf8lPw0DUrpOvWA44DduL4ck5EfCRtw/PwXfdOadoBgvbDcEFjvMxC6byUPFGrRSWW+1+EpNeZXFrjbvM+3vqiYme9KT6awTJz+oCpIaKurG1VBq+9AJAzCzsBG6u+CAT0nkwr4AfxfFyqWuUgg5NHnZz0vMpLtOSq8BQLSwqYxQOlwxOWS3CvvzG3+8AcV4OLow+hRxZBk7srbn2iGr4Ng3JaLNtAgMBAAECggEAaJOddH11FlibeXYbtqAMaoEAFULNwEZoA7Kx5ZP813XJj8VRFSOOmmAMikbBuOAhZrMgYdIvbr3KmuCywtuJ3pJL51lt3bzmuOoVIu/GAvbRxZXhoH2hX9QpCe7ZSNDCO5Ce6LyBcdFKIJFjLesxIYmZ2MA5cIZ3PlUcm7yPw2A2RySADEbUBuhtkKzQay475SfM3i+UGvBFcwJaMSOdKJAsRn6mTZ9doOy08EHB5CZDYIiJq3xA85DjwCKVL000K9ne/9zlzg7xE6PX/A31Gu3tFq4+tBLeEZcSYyJOnJbbw9hvVQ5a1q6pM3gdTkKgnY4yVTJ+992lS1J1+RULGQKBgQDj1TGM5aNsYPEXxxk/vPbM69TzurPLHUvUmKbL3CvZE5WFSUBmO7kSfw66cAhwiJClFn0U4ueYWBIwAKbutFCTgKtRUSNDphXGcHB/Gkg3iL64wRs4kIAGIgYQmlAW0NH8dXrDwZ7ApTxGaEHvRC8F8Fh5L3qPhLeW7uaUmztMkwKBgQDXxgxJ/MpwIGtnbwbDVJQDeo6j5MeeWi7Ia7H1ApElrRjcFbxIOdE4ZNQFLd0sPjhFzf6giQjHXSAZsuwJhLBEvWqRfGBfJCvRLOiknlg2k+vHhdaOas9ZCvr9Nlsd1ql9oWrRl15NwG9D52OMXOC0TAZVrcldWuayfTJ8U0v//wKBgCSnuEEi8RgOwLtCnR1UGaD+kFRmRWb4X6rkpHFICwXx0KyRDHtmQHBpYMU+IR1520u0QouJthkcklCGylS9TfltSiLbGwFXR0mV7YOFhvjoV0cCSo7fMLnL343sRdZl4mLrw8Sa8h+sdfYd7/2+ypH6CUH2EZHlmGQAK7jdAL1hAoGACGEPfxwK/Hm10gl0uMcjDFOJEIJE4jhcUroj6gDUhCMJsRpC+ocMQeVgemcCjMJJyyQpvDA2IA/UvEq/ccsuUS0N42JyF5++99uHmUTw5gWuhUwEPfmV3b5YatbeiPUaFd/b1xHKvrg3Weq1afD9ZOMC5/bct/xcsxe7iyps7B8CgYAqlgRteJI2QTlLSaBmZbuEzZkqy968+ha4WNMaDm8nH6VUST+FhW1dd4sNiaSgbWqfxWEwuPuoCkUvXI+vxOyS/rsX9P1gLhYKYqUEXL8Lo08KV+wB9hRWwstrc4XwZGV0mVHybcClyenpGL3ywI0KEYoOlcw9iYUrwf2KSQ3Anw==";


        //    var privateKey = math.Cert_PrivateKey;
        //    byte[] keyData = Convert.FromBase64String(privateKey);

        //    using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob))
        //    using (RSACng rsa = new RSACng(cngKey))
        //    {
        //        byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
        //        return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
        //    }
        //}

        public static string Sign(string message, Merchant math)
        {
            return RSAHelper.Sign_SHA256(message, math.Cert_Path, math.MachId);
        }
        private static int GetTimeStamp()
        {
            var utcNow = DateTime.Now;
            var timeSpan = utcNow - new DateTime(1970, 1, 1, 8, 0, 0);
            return (int)timeSpan.TotalSeconds;
        }
    }
}